# Test for page level predicate locking in gin index
#
# Test to verify serialization failures and to check reduced false positives
#
# To verify serialization failures, queries and permutations are written in such
# a way that an index scan  (from one transaction) and an index insert (from
# another transaction) will try to access the same part (sub-tree) of the index
# whereas to check reduced false positives, they will try to access different
# parts (sub-tree) of the index.


setup
{
  create table gin_tbl(p int4[]);
  insert into gin_tbl select array[1] from generate_series(1, 8192) g;
  insert into gin_tbl select array[g] from generate_series(2, 800) g;
  create index ginidx on gin_tbl using gin(p) with (fastupdate = off);
  create table other_tbl(v int4);
}

teardown
{
  drop table gin_tbl;
  drop table other_tbl;
}

session "s1"
setup
{
  begin isolation level serializable;
  set enable_seqscan=off;
}

step "ra1"	{ select * from gin_tbl where p @> array[1] limit 1; }
step "rb1"  { select count(*) from gin_tbl where p @> array[2]; }
step "rc1"  { select count(*) from gin_tbl where p @> array[800]; }
step "rd1"  { select count(*) from gin_tbl where p @> array[2000]; }

step "wo1"	{ insert into other_tbl values (1); }

step "c1"  { commit; }

session "s2"
setup
{
  begin isolation level serializable;
  set enable_seqscan=off;
}

step "ro2"	{ select count(*) from other_tbl; }

step "wa2"  { insert into gin_tbl values (array[1]); }
step "wb2"  { insert into gin_tbl values (array[2]); }
step "wc2"  { insert into gin_tbl values (array[800]); }
step "wd2"  { insert into gin_tbl values (array[2000]); }

step "c2"  { commit; }

session "s3"
step "fu" { alter index ginidx set (fastupdate = on); }

# An index scan (from one transaction) and an index insert (from another
# transaction) try to access the same part of the index. So, there is a
# r-w conflict.

permutation "ra1" "ro2" "wo1" "c1" "wa2" "c2"
permutation "ro2" "ra1" "wo1" "c1" "wa2" "c2"
permutation "ro2" "ra1" "wo1" "wa2" "c1" "c2"
permutation "ra1" "ro2" "wa2" "wo1" "c1" "c2"

permutation "rb1" "ro2" "wo1" "c1" "wb2" "c2"
permutation "ro2" "rb1" "wo1" "c1" "wb2" "c2"
permutation "ro2" "rb1" "wo1" "wb2" "c1" "c2"
permutation "rb1" "ro2" "wb2" "wo1" "c1" "c2"

permutation "rc1" "ro2" "wo1" "c1" "wc2" "c2"
permutation "ro2" "rc1" "wo1" "c1" "wc2" "c2"
permutation "ro2" "rc1" "wo1" "wc2" "c1" "c2"
permutation "rc1" "ro2" "wc2" "wo1" "c1" "c2"

# An index scan (from one transaction) and an index insert (from another
# transaction) try to access different parts of the index.  So, there is no
# r-w conflict.

permutation "ra1" "ro2" "wo1" "c1" "wb2" "c2"
permutation "ro2" "ra1" "wo1" "c1" "wc2" "c2"
permutation "ro2" "rb1" "wo1" "wa2" "c1" "c2"
permutation "rc1" "ro2" "wa2" "wo1" "c1" "c2"

permutation "rb1" "ro2" "wo1" "c1" "wa2" "c2"
permutation "ro2" "rb1" "wo1" "c1" "wc2" "c2"
permutation "ro2" "ra1" "wo1" "wb2" "c1" "c2"
permutation "rc1" "ro2" "wb2" "wo1" "c1" "c2"

permutation "rc1" "ro2" "wo1" "c1" "wa2" "c2"
permutation "ro2" "rc1" "wo1" "c1" "wb2" "c2"
permutation "ro2" "ra1" "wo1" "wc2" "c1" "c2"
permutation "rb1" "ro2" "wc2" "wo1" "c1" "c2"

# With fastupdate = on all index is under predicate lock.  So we can't
# distinguish particular keys.

permutation "fu" "ra1" "ro2" "wo1" "c1" "wa2" "c2"
permutation "fu" "ra1" "ro2" "wo1" "c1" "wb2" "c2"

# Check fastupdate turned on concurrently.

permutation "ra1" "ro2" "wo1" "c1" "fu" "wa2" "c2"

# Tests for conflicts with previously non-existing key

permutation "rd1" "ro2" "wo1" "c1" "wd2" "c2"
permutation "ro2" "rd1" "wo1" "c1" "wd2" "c2"
permutation "ro2" "rd1" "wo1" "wd2" "c1" "c2"
permutation "rd1" "ro2" "wd2" "wo1" "c1" "c2"
